#include "mini.kit/hash.h"

namespace MINIKIT
{

#define mix(a,b,c) \
{ \
  a -= b; a -= c; a ^= (c >> 13); \
  b -= c; b -= a; b ^= (a << 8); \
  c -= a; c -= b; c ^= (b >> 13); \
  a -= b; a -= c; a ^= (c >> 12);  \
  b -= c; b -= a; b ^= (a << 16); \
  c -= a; c -= b; c ^= (b >> 5); \
  a -= b; a -= c; a ^= (c >> 3);  \
  b -= c; b -= a; b ^= (a << 10); \
  c -= a; c -= b; c ^= (b >> 15); \
}

uint32_t Hash::bobHash(void *val, uint32_t length)                                                     
{  
   unsigned char *k = (unsigned char *)val;                                                     
   uint32_t a,b,c,len; 
                                                                                                     
   /* Set up the internal state */                                                                   
   len = length; 
   a = b = c = 0x9e3779b9;  /* the golden ratio; an arbitrary value */                               
      
   /* Handle most of the key */                                                                      
   while (len >= 12)
   {                                                                                                 
      a += (k[0] +((uint32_t)k[1] << 8) +((uint32_t)k[2] << 16) +((uint32_t)k[3] << 24));
      b += (k[4] +((uint32_t)k[5] << 8) +((uint32_t)k[6] << 16) +((uint32_t)k[7] << 24));
      c += (k[8] +((uint32_t)k[9] << 8) +((uint32_t)k[10]<< 16)+((uint32_t)k[11] << 24));
      mix(a,b,c);
      k += 12; len -= 12;                                                                            
   }                                                                                                 
   
   /* Handle the last 11 bytes */                                                                    
   c += length;             
   switch(len)/* all the case statements fall through */                               
   {   
       case 11: c+=((uint32_t)k[10] << 24);                                                     
       case 10: c+=((uint32_t)k[9]  << 16);                                                     
       case 9 : c+=((uint32_t)k[8]  << 8);
       /* the first byte of c is reserved for the length */                                          
       case 8 : b+=((uint32_t)k[7] << 24);                                                      
       case 7 : b+=((uint32_t)k[6] << 16);                                                      
       case 6 : b+=((uint32_t)k[5] << 8);                                                       
       case 5 : b+=k[4];
       case 4 : a+=((uint32_t)k[3] << 24);                                                      
       case 3 : a+=((uint32_t)k[2] << 16);                                                      
       case 2 : a+=((uint32_t)k[1] << 8);                                                       
       case 1 : a+=k[0];                                                                             
   }
   mix(a,b,c);                                                                                       
   
   return c;                                                                                         
}
#undef mix

} //namespace MINIKIT

